package com.zzy.mccjt.retelimiter.method;

import lombok.extern.slf4j.Slf4j;
import org.springframework.asm.Type;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: mccjt-cloud
 * @description: EL表达式
 * @author: zhouyang.zheng
 * @create: 2022-08-01 16:52
 **/
@Slf4j
public class ExpressionUtil {
    private static ConcurrentHashMap<String, ExpressionEvaluator> expressionEvaluatorCache = new ConcurrentHashMap<>();

    public static Object evalKey(LimiterContext context, String keyScript, Method defineMethod) {
        try {
            String key = getKey(defineMethod);
            ExpressionEvaluator expressionEvaluator = expressionEvaluatorCache.get(key);
            if (expressionEvaluator == null) {
                expressionEvaluator = new ExpressionEvaluator(keyScript, defineMethod);
                expressionEvaluatorCache.put(key, expressionEvaluator);
            }
            return expressionEvaluator.apply(context);
        } catch (Exception e) {
            log.error("error occurs when eval key \"" + keyScript + "\" in " + context.getMethod() + ":" + e.getMessage(), e);
            return null;
        }
    }

    private static String getKey(Method method) {
        StringBuilder sb = new StringBuilder();
        sb.append(method.getDeclaringClass().getName());
        sb.append('.');
        sb.append(method.getName());
        sb.append(Type.getMethodDescriptor(method));
        return sb.toString();
    }
}
